﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace SuperKit
{
    /// <summary>
    /// SuperPlayer.xaml 的交互逻辑
    /// </summary>
    public partial class SuperPlayer : Window {
        private ConfigReader Cfg => ConfigReader.Instance;
        private OpenFileDialog fileDialog;
        private DateTime lastBuffering;
        public const double BUFFERING_INTERVAL = 0.1f;
        public DispatcherTimer timer;
        private bool _isManualChange;
        private bool isPlaying;
        public DateTime _manualControl = DateTime.Now;
        public const double MANUAL_INTERVAL = 1.0f;
        public ObservableCollection<SuperPlayerViewModel> file_source;
        public ObservableCollection<ClipCatalog> clip_source;
        private ClipCatalog _clip_points;
        private ClipCatalog _clip_spans;
        private SuperPlayerViewModel CurrentItem { get; set; }
        private int CurrentPosition => (int)player.Position.TotalSeconds;
        private int TotalLength => (int)player.NaturalDuration.TimeSpan.TotalSeconds;
        public string DirPath { get; internal set; }
        public bool IsNeedSaveConfig { get; set; } = false;
        private int Volume { get; set; }
        public string MediaSource { get; internal set; }

        public StringBuilder logs;

        public SuperPlayer() {
            InitializeComponent();
            logs = new StringBuilder();
        }


        private void Window_Loaded(object sender, RoutedEventArgs e) {
            Volume = Cfg.Volume;
            slider_volume.Value = Volume;

            player.LoadedBehavior = MediaState.Manual;

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(0.1f);
            timer.Tick += Timer_Tick;
            timer.Start();

            txt_video_bytes.Text = $"{Cfg.DefaultBytesRate:N1}";

            SetTitle(MediaSource);
            if (Kit.IsEmpty(MediaSource) == false) {
                LoadFile(MediaSource);
            } else {
                Reload();
            }
        }

        private void Reload() {
            LoadDirectory(new DirectoryInfo(DirPath));
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
            if (IsNeedSaveConfig) {
                Cfg.Save();
            }
        }

        private void LoadDirectory(DirectoryInfo? directory) {
            DirPath = directory.FullName;
            file_source = new ObservableCollection<SuperPlayerViewModel>();
            var files = directory.GetFiles();
            foreach (var file in files) {
                if (Kit.IsFileType(file, Kit.MEDIA_EXT)) {
                    file_source.Add(new SuperPlayerViewModel(file));
                }
            }

            tree_files.ItemsSource = file_source;
        }


        private void LoadFile(string path) {
            LoadDirectory(new FileInfo(path).Directory);
            Play(path);
        }

        private void Open_Click(object sender, RoutedEventArgs e) {
            fileDialog ??= new OpenFileDialog();
            if (fileDialog.ShowDialog() == true) {
                LoadFile(fileDialog.FileName);
            }
        }

        private void Play(string path) {
            Uri uri = new Uri(path);
            player.Source = uri;
            player.Volume = Volume * 0.01;
            player.Play();
            isPlaying = true;
            RefreshPlayButton();

            SelectCurrent(path);
        }

        private void SelectCurrent(string path) {
            foreach (var i in file_source) {
                if (Kit.IsEqual(i.Info.FullName, path)) {
                    CurrentItem = i;
                    return;
                }
            }
        }

        private void Timer_Tick(object sender, EventArgs e) {
            //SetupPanel();
            SetupMedia();
        }



        private void SetupMedia() {
            var time = DateTime.Now - _manualControl;
            if (time.TotalSeconds < MANUAL_INTERVAL) return;

            if (!isPlaying) return;
            if (!player.NaturalDuration.HasTimeSpan) return;
            _isManualChange = true;
            double percent = player.Position.TotalSeconds / player.NaturalDuration.TimeSpan.TotalSeconds;
            slider.Value = slider.Maximum * percent;
            RefreshLabel();

            _isManualChange = false;
        }

        private void RefreshLabel() {
            label_current.Content = Kit.FormatTime(CurrentPosition);
            label_duration.Content = Kit.FormatTime(TotalLength);
        }

        private void SetTitle(object? obj) {
            var str = obj == null ? "" : obj.ToString();
            Title = $"超级播放器 - {str}";
        }

        private void Error(string str) {
            SetTitle(str);
        }


        private void OpenMain_Click(object sender, RoutedEventArgs e) {
            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();
        }

        private void Settings_Click(object sender, RoutedEventArgs e) {
            SettingsWindow settingsWindow = new SettingsWindow();
            settingsWindow.ShowDialog();
        }

        private void Exit_Click(object sender, RoutedEventArgs e) {
            Close();
        }

        private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
            var buffering = DateTime.Now - lastBuffering;
            if (buffering.TotalSeconds < BUFFERING_INTERVAL) return;
            lastBuffering = DateTime.Now;
            _manualControl = DateTime.Now;

            if (_isManualChange == false && player.HasVideo) {
                var percent = slider.Value / slider.Maximum;
                var second = player.NaturalDuration.TimeSpan.TotalSeconds * percent;
                player.Position = TimeSpan.FromSeconds(second);
                SetTitle(Kit.FormatTime((int)second));
                RefreshLabel();
            }


        }


        private void Play_Click(object sender, RoutedEventArgs e) {
            Resume();
        }

        private void RefreshPlayButton() {
            button_play.Visibility = isPlaying ? Visibility.Collapsed : Visibility.Visible;
            button_pause.Visibility = isPlaying ? Visibility.Visible : Visibility.Collapsed;
        }

        private void Pause_Click(object sender, RoutedEventArgs e) {
            Pause();
        }

        private void Resume() {
            player.Play();
            isPlaying = true;
            RefreshPlayButton();
        }


        private void Pause() {
            player.Pause();
            isPlaying = false;
            RefreshPlayButton();
        }

        private void Player_Click(object sender, MouseButtonEventArgs e) {
            if (isPlaying) {
                Pause();
            } else {
                Resume();
            }
        }

        private void Cut_Click(object sender, RoutedEventArgs e) {
            if (CurrentItem == null) {
                Error("当前没有选定播放项目！");
                return;
            }

            CurrentItem.AddCut(CurrentPosition, TotalLength);
            RefreshClips();
        }

        private void Cut_Input(object sender, RoutedEventArgs e) {
            if (CurrentItem == null) {
                Error("当前没有选定播放项目！");
                return;
            }
            TimeSpan timeSpan = TimeSpan.Parse(txt_input_time.Text);
            CurrentItem.AddCut((int)timeSpan.TotalSeconds, TotalLength);
            RefreshClips();
        }

        private void Clip_Delete_Click(object sender, RoutedEventArgs e) {
            if (CurrentItem == null) {
                Error("当前没有选定播放项目！");
                return;
            }
            var item = tree_clips.SelectedItem as ClipBase;
            if (item != null && item.ClipType == ClipType.Point) {
                CurrentItem.Clips.RemovePoint((ClipPoint)item);
                RefreshClips();
                return;
            }

        }

        private void RefreshClips() {
            if (CurrentItem == null) {
                return;
            }

            clip_source ??= new ObservableCollection<ClipCatalog>();
            _clip_points ??= new ClipCatalog("分割点");
            _clip_spans ??= new ClipCatalog("分段");
            clip_source.Clear();
            clip_source.Add(_clip_points);
            clip_source.Add(_clip_spans);

            CurrentItem.Clips.Fill(_clip_points, _clip_spans);

            tree_clips.ItemsSource = clip_source;
        }

        private void Finish_Click(object sender, RoutedEventArgs e) {
            if (CurrentItem == null) {
                return;
            }



            List<MediaCutter> cutters = new List<MediaCutter>();
            int index = 0;
            foreach (var i in CurrentItem.Clips.spans) {
                if (i.Checked) {
                    var item = new MediaCutter(CurrentItem.Info.FullName, index++, i.Start, i.End);
                    cutters.Add(item);
                }
            }
            Media.Execute(cutters, OnFlush, OnFinish);
        }

        private void OnFinish(string msg) {
            this.Dispatcher.Invoke(() => {
                Reload();
            });
        }

        private void OnFlush(string msg) {
            this.Dispatcher.Invoke(new Action(() => {
                label_console.Content = msg;
                logs.Append(msg);
                logs.Append("\r\n");
            }));
        }

        private void Combine_Click(object sender, RoutedEventArgs e) {
            OnCombine(true);
        }

        private void Combine_Compress_Click(object sender, RoutedEventArgs e) {
            OnCombine(false);
        }

        private void OnCombine(bool isCopy) {
            var width = Kit.ParseInt(txt_width.Text);
            var height = Kit.ParseInt(txt_height.Text);
            var bytesRate = Kit.ParseFloat(txt_video_bytes.Text);
            Cfg.DefaultBytesRate = bytesRate;
            IsNeedSaveConfig = true;

            List<MediaCombiner> list = new List<MediaCombiner>();
            StringBuilder sb = new StringBuilder();
            int index = 0;
            foreach (var i in file_source) {
                if (i.Checked) {
                    var item = new MediaCombiner(i.Info.FullName, width, height, bytesRate);
                    list.Add(item);
                    sb.Append($"{item.FullName}\r\n");
                }
            }

            // 只有一个项目时，不处理
            if (list.Count <= 1) {
                return;
            }

            Media.ExecuteCombine(list, isCopy, OnFlush, OnFinish);
        }

        private void Rename_Click(object sender, RoutedEventArgs e) {
            var item = tree_files.SelectedItem as SuperPlayerViewModel;
            if (item != null) {
                item.Rename(txt_name.Text);
            }
        }

        public bool IsClickPlay() {
            return check_ClickPlay.IsChecked == true;
        }


        private void sliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
            Volume = (int)slider_volume.Value;
            Cfg.Volume = Volume;
            IsNeedSaveConfig = true;
            player.Volume = Volume * 0.01;
        }

        private void tree_files_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) {
            var item = tree_files.SelectedItem as SuperPlayerViewModel;
            if (item != null) {
                SetTitle(item);                
                txt_name.Text = item.Name;
                if (IsClickPlay()) {
                    Play(item.Info.FullName);
                }
            }
        }

        private void tree_files_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
            var item = tree_files.SelectedItem as SuperPlayerViewModel;
            if (item != null) {
                SetTitle(item);
                if (!IsClickPlay()) {
                    Play(item.Info.FullName);
                }
            }            
        }

        private void ShowLogs_Click(object sender, MouseButtonEventArgs e) {
            LogsWindow dlg = new LogsWindow();
            dlg.Logs = logs.ToString();
            dlg.ShowDialog();
        }

        private void Remove_Click(object sender, RoutedEventArgs e) {
            var dir = Path.Combine(DirPath, txtRemoveDir.Text);
            if (Directory.Exists(dir) == false) {
                Directory.CreateDirectory(dir);
            }

            foreach (var i in file_source) {
                if (i.Checked) {
                    var deletePath = Path.Combine(dir, i.Name);
                    if (File.Exists(deletePath)) {
                        continue;
                    }
                    File.Move(i.Info.FullName, deletePath);
                }
            }
            Reload();
        }

        private void AllSelect_Click(object sender, RoutedEventArgs e) {
            foreach (var i in file_source) {
                i.Checked = true;
            }
        }

        private void UnSelect_Click(object sender, RoutedEventArgs e) {
            foreach (var i in file_source) {
                i.Checked = !i.Checked;
            }
        }

        private void Refresh_Click(object sender, RoutedEventArgs e) {
            Reload();
        }

    }
}
